﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using iNet.Media.Imaging;
using iNet.Tasks;

namespace iNet.Media
{
	/// <summary>
	/// 表示媒體解碼工作的基底類別。
	/// </summary>
	public abstract class MediaDecodeTask : MediaTask
	{
		#region 欄位
		IMetadata _DecodedMetadata;
		IImage _DecodedThumbnailImage;
		IMediaFormat _DecodingFormat;
		MediaDecodeRequests _MediaDecodeRequests;
		MediaStorage _Source;
		int _SourceLockTimeout = 5000;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 MediaDecodeTask 執行個體。
		/// </summary>
		protected MediaDecodeTask()
		{ }
		/// <summary>
		/// 初始化新的 MediaDecodeTask 執行個體。
		/// </summary>
		/// <param name="decodingFormat">媒體的解碼格式。</param>
		protected MediaDecodeTask(IMediaFormat decodingFormat)
			: this(decodingFormat, null, 0)
		{ }
		/// <summary>
		/// 初始化新的 MediaDecodeTask 執行個體。
		/// </summary>
		/// <param name="decodingFormat">媒體的解碼格式。</param>
		/// <param name="source">媒體儲存來源。</param>
		protected MediaDecodeTask(IMediaFormat decodingFormat, MediaStorage source)
			: this(decodingFormat, source, 0)
		{ }
		/// <summary>
		/// 初始化新的 MediaDecodeTask 執行個體。
		/// </summary>
		/// <param name="decodingFormat">媒體的解碼格式。</param>
		/// <param name="source">媒體儲存來源。</param>
		/// <param name="requests">解碼請求。</param>
		protected MediaDecodeTask(IMediaFormat decodingFormat, MediaStorage source, MediaDecodeRequests requests)
		{
			_DecodingFormat = decodingFormat;
			_Source = source;
			_MediaDecodeRequests = requests;
		}
		#endregion
		#region Decode
		/// <summary>
		/// 解碼媒體。
		/// </summary>
		/// <param name="version">工作版本。</param>
		/// <param name="source">媒體儲存來源。</param>
		/// <param name="requests">解碼請求。</param>
		/// <returns>True 表示解碼完成，False 表示解碼失敗。</returns>
		protected abstract bool Decode(TaskVersion version, MediaStorage source, MediaDecodeRequests requests);
		#endregion
		#region DecodedMetadata
		/// <summary>
		/// 取得已解碼的中繼資料。
		/// </summary>
		public IMetadata DecodedMetadata
		{
			get
			{
				return _DecodedMetadata;
			}
		}
		#endregion
		#region DecodedThumbnailImage
		/// <summary>
		/// 取得已解碼的內嵌縮圖。
		/// </summary>
		public IImage DecodedThumbnailImage
		{
			get
			{
				return _DecodedThumbnailImage;
			}
		}
		#endregion
		#region DecodingFormat
		/// <summary>
		/// 取得支援解碼的特定媒體格式，Null (Visual Basic 為 Nothing) 表示沒有特定的格式。
		/// </summary>
		public virtual IMediaFormat DecodingFormat
		{
			get
			{
				return _DecodingFormat;
			}
		}
		#endregion
		#region Execute
		/// <summary>
		/// 執行工作。
		/// </summary>
		/// <param name="version">工作版本。</param>
		/// <returns>True 表示工作執行成功，False 表示執行失敗。</returns>
		protected override bool Execute(TaskVersion version)
		{
			//取得參數
			MediaStorage source;
			MediaDecodeRequests requests;
			if (!this.ReadValue<MediaStorage>(version, ref _Source, out source) ||
				!this.ReadValue<MediaDecodeRequests>(version, ref _MediaDecodeRequests, out requests))
				return true;

			//確認參數
			if (source == null)
				throw new ArgumentException();

			//解碼
			if (this.Decode(version, source, requests))
				return true;

			//解碼失敗
			throw new MediaDecodeFailedException(MediaDecodeFailedReason.Unknown);
		}
		#endregion
		#region MediaDecodeRequests
		/// <summary>
		/// 取得或設定解碼請求組合。
		/// </summary>
		public MediaDecodeRequests MediaDecodeRequests
		{
			get
			{
				return _MediaDecodeRequests;
			}
			set
			{
				this.SetInitializingParameter<MediaDecodeRequests>(ref _MediaDecodeRequests, value);
			}
		}
		#endregion
		#region ResetOverride
		/// <summary>
		/// 重設工作狀態。
		/// </summary>
		protected override void ResetOverride()
		{
			//呼叫基底
			base.ResetOverride();

			//重設欄位
			_DecodedMetadata = null;
			_DecodedThumbnailImage = null;
		}
		#endregion
		#region SetDecodedMetadata
		/// <summary>
		/// 設定已解碼的中繼資料。
		/// </summary>
		/// <param name="version">工作版本。</param>
		/// <param name="metadata">中繼資料。</param>
		/// <exception cref="ArgumentNullException">version 為 Null (Visual Basic 為 Nothing)。</exception>
		protected void SetDecodedMetadata(TaskVersion version, IMetadata metadata)
		{
			//儲存結果
			this.WriteValue<IMetadata>(version, ref _DecodedMetadata, metadata);

			//引發事件
			if (metadata != null)
				this.RaiseEvent<DataEventArgs<IMetadata>>(version, this.MetadataDecoded, new DataEventArgs<IMetadata>(metadata));
		}
		#endregion
		#region SetDecodedThumbnailImage
		/// <summary>
		/// 設定已解碼的內嵌縮圖。
		/// </summary>
		/// <param name="version">工作版本。</param>
		/// <param name="image">內嵌縮圖。</param>
		/// <exception cref="ArgumentNullException">version 為 Null (Visual Basic 為 Nothing)。</exception>
		protected void SetDecodedThumbnailImage(TaskVersion version, IImage image)
		{
			//儲存結果
			this.WriteValue<IImage>(version, ref _DecodedThumbnailImage, image);

			//引發事件
			if (image != null)
				this.RaiseEvent<DataEventArgs<IImage>>(version, this.ThumbnailImageDecoded, new DataEventArgs<IImage>(image));
		}
		#endregion
        #region SupportedMediaDecodeRequests
		/// <summary>
		/// 取得支援的解碼請求組合。
		/// </summary>
		public virtual MediaDecodeRequests SupportedMediaDecodeRequests
        {
			get
            {
                return Media.MediaDecodeRequests.DecodeMetadata | Media.MediaDecodeRequests.DecodeThumbnailImage;
            }
        }
        #endregion
		#region Source
		/// <summary>
		/// 取得或設定媒體儲存來源。
		/// </summary>
		public MediaStorage Source
		{
			get
			{
				return _Source;
			}
			set
			{
				this.SetInitializingParameter<MediaStorage>(ref _Source, value);
			}
		}
		#endregion
		#region SourceLockTimeout
		/// <summary>
		/// 取得或設定鎖定媒體儲存來源的最長嘗試時間，單位為毫秒。零表示失敗後立即返回，預設值為 5000。
		/// </summary>
		public int SourceLockTimeout
		{
			get
			{
				return _SourceLockTimeout;
			}
			set
			{
				if (value < 0)
					throw new ArgumentOutOfRangeException();
				this.SetInitializingParameter<int>(ref _SourceLockTimeout, value);
			}
		}
		#endregion
		#region 事件
		/// <summary>
		/// 發生在中繼資料解碼完成後。
		/// </summary>
		public event EventHandler<DataEventArgs<IMetadata>> MetadataDecoded;
		/// <summary>
		/// 發生在縮圖解碼完成後。
		/// </summary>
		public event EventHandler<DataEventArgs<IImage>> ThumbnailImageDecoded;
		#endregion
	}
	#region MediaDecodeRequests
	/// <summary>
	/// 表示媒體解碼的工作要求。
	/// </summary>
	[Flags]
	public enum MediaDecodeRequests
	{
		/// <summary>
		/// 全部請求。
		/// </summary>
		All = (DecodeMetadata | DecodeThumbnailImage),
		/// <summary>
		/// 解碼中繼資料。
		/// </summary>
		DecodeMetadata = 0x1,
		/// <summary>
		/// 解碼內嵌縮圖。
		/// </summary>
		DecodeThumbnailImage = 0x2,
	}
	#endregion
}
